package com.pay.order.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pay.common.utils.Result;
import com.pay.order.pojo.TGoods;
import com.pay.order.pojo.TOrder;
import com.pay.order.service.TOrderService;
import com.pay.order.mapper.TOrderMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
* @author 28242
* @description 针对表【t_order(订单主表)】的数据库操作Service实现
* @createDate 2025-08-08 17:15:05
*/
@Service
@Slf4j
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder>
    implements TOrderService{

    private static final String BATCH_ORDER_LOCK_KEY = "batch:order:lock:%s";
    private static final String STOCK_LOCK_KEY = "stock:lock:%s";
    private static final String ORDER_CACHE_PREFIX = "order:cache:";


    @Autowired
    private HttpServletRequest request;

    @Autowired
    private TOrderMapper tOrderMapper;



    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Autowired
    private RedissonClient redissonClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addOrder(List<TOrder> tOrders) {

        if (tOrders == null || tOrders.isEmpty()) {
            return Result.error().setMsg("订单列表不能为空");
        }
        String token = request.getHeader("token");
        if (token == null) {
            return Result.error().setMsg("token不能为空");
        }
        Claims body = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        Long userId = body.get("userId", Long.class);

        for (TOrder tOrder : tOrders) {
            tOrder.setUserId(userId);
        }


        // 生成批次号
        Snowflake snowflake = new Snowflake(1, 1);
        String batchNo = String.valueOf(snowflake.nextId());

        // 1. 对整个批次加分布式锁
        RLock lock = redissonClient.getLock(String.format(BATCH_ORDER_LOCK_KEY, batchNo));
        try {
            if (!lock.tryLock(30, TimeUnit.SECONDS)) {
                return Result.error().setMsg("订单正在处理，请勿重复提交");
            }

            // 2. 处理每个订单
            List<String> orderNos = new ArrayList<>();
            for (TOrder order : tOrders) {
                // 为每个订单生成唯一订单号
                String orderNo = String.valueOf(snowflake.nextId());
                order.setOrderNo(orderNo);
                order.setCreateTime(new Date());
                order.setUpdateTime(new Date());
                order.setStatus(0); // 待支付状态

                // 3. 扣减库存（对每个商品加锁）
                if (order.getItems() != null && !order.getItems().isEmpty()) {
                    for (TGoods item : order.getItems()) {
                        RLock stockLock = redissonClient.getLock(String.format(STOCK_LOCK_KEY, item.getGoodId()));
                        try {
                            if (!stockLock.tryLock(10, TimeUnit.SECONDS)) {
                                throw new RuntimeException("获取商品库存锁超时");
                            }

                            // 扣减库存（这里需要你实现真实的库存扣减逻辑）
                            boolean success = deductStock(item.getGoodId(), item.getQuantity());
                            if (!success) {
                                throw new RuntimeException("商品 " + item.getGoodId() + " 库存不足");
                            }
                        } finally {
                            if (stockLock.isHeldByCurrentThread()) {
                                stockLock.unlock();
                            }
                        }
                    }
                }

                // 4. 发送到MQ并缓存到Redis
                handleOrderProcessing(order);
                orderNos.add(orderNo);
            }

            // 返回所有订单号
            Map<String, Object> result = new HashMap<>();
            result.put("batchNo", batchNo);
            result.put("orderNos", orderNos);
            return Result.ok().setData(result);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return Result.error().setMsg("系统繁忙，请稍后重试");
        } catch (Exception e) {
            return Result.error().setMsg(e.getMessage());
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 处理单个订单发送到MQ和缓存到Redis
     */
    private void handleOrderProcessing(TOrder order) {
        try {
            // 1. 将订单信息发送到RabbitMQ
            rabbitTemplate.convertAndSend("order.exchange", "order.create", order);

            // 2. 同时将订单信息缓存到Redis中
            String cacheKey = ORDER_CACHE_PREFIX + order.getOrderNo();
            redisTemplate.opsForValue().set(cacheKey, JSONObject.toJSONString(order), 30, TimeUnit.MINUTES);
        } catch (Exception e) {
            throw new RuntimeException("订单处理失败: " + e.getMessage());
        }
    }

    /**
     * 模拟扣减库存方法
     * 实际项目中应该调用商品服务的真实扣库存方法
     */
    private boolean deductStock(Long goodsId, Integer quantity) {
        // 这里应该调用真实的商品服务扣库存方法
        // 暂时返回true模拟成功
        TGoods tGoods = tOrderMapper.selectGoodById(goodsId);
        if (tGoods.getStock()>quantity){
            log.info("模拟扣减库存: 商品ID={}, 数量={}", goodsId, quantity);
            int  i=  tOrderMapper.deductStock(goodsId,quantity);;

            if (i>0){
                return true;
            }
        }
      return false;
    }

    /**
     * 从缓存中获取订单信息
     */
    public TOrder getOrderFromCache(String orderNo) {
        String cacheKey = ORDER_CACHE_PREFIX + orderNo;
        String s = redisTemplate.opsForValue().get(cacheKey);
        TOrder tOrder = JSONObject.parseObject(s, TOrder.class);
        return tOrder;
    }

    /**
     * 监听订单创建队列
     * 采用多线程模式处理批量订单
     */
    @RabbitListener(queues = "order.queue", concurrency = "5-10")
    public void handleOrderCreate(TOrder order) {
        try {
            log.info("开始处理订单: {}", order.getOrderNo());

            // 1. 将订单信息保存到MySQL数据库
            tOrderMapper.insert(order);
            log.info("订单已保存到数据库: {}", order.getOrderNo());

            // 2. 删除Redis中的订单缓存
            String cacheKey = ORDER_CACHE_PREFIX + order.getOrderNo();
            Boolean deleted = redisTemplate.delete(cacheKey);
            if (Boolean.TRUE.equals(deleted)) {
                log.info("订单缓存已删除: {}", order.getOrderNo());
            } else {
                log.warn("订单缓存不存在或删除失败: {}", order.getOrderNo());
            }

        } catch (Exception e) {
            log.error("处理订单失败: {}", order.getOrderNo(), e);
            throw e;
        }
    }
}




